home *** CD-ROM | disk | FTP | other *** search
/ Carousel Volume 2 #1 / carousel.iso / mactosh / lang / p_image1.sit / LSP Source / Image.p < prev    next >
Encoding:
Text File  |  1989-07-29  |  55.3 KB  |  2,340 lines

  1. program Image;
  2.  
  3. {Image is a program for the Macintosh II for acquiring, enhancing, analyzing, editing,}
  4. {pseudocoloring, printing, and animating grayscale and color images.}
  5.  
  6.  
  7. {Version 1.16 , 21-July-1989}
  8.  
  9.  
  10. {Developed using Lightspeed Pascal 2.0 and Turbo Pascal Numerical Toolbox Methods.}
  11.  
  12.  
  13. {Author :}
  14.  
  15. {Wayne Rasband}
  16. {National Institutes of Health}
  17. {Bethesda , MD}
  18.  
  19. {BitNet: wsr@nihcu}
  20. {Internet: wayne@alw.nih.gov}
  21. {CompuServe: 76067,3454}
  22.  
  23.  
  24.     uses
  25.         QuickDraw, OSIntf, ToolIntf, PrintTraps, globals, Utilities, Initialization, FileUnit, Analysis, Graphics, edit, Functions, Camera, User;
  26.  
  27. {$I-}
  28.  
  29.  
  30. {PROCEDURE MacsBug; inline $a9ff;}
  31.  
  32.  
  33.     procedure InvertPalette;
  34.         var
  35.             TempRed, TempGreen, TempBlue: ColorArrayX;
  36.             i, LastColor: integer;
  37.             TempTable: MyCSpecArray;
  38.     begin
  39.         with info^ do begin
  40.                 if LutMode = ColorPalette then begin
  41.                         TempRed := RedX;
  42.                         TempGreen := GreenX;
  43.                         TempBlue := BlueX;
  44.                         LastColor := ncolors - 1;
  45.                         for i := 0 to LastColor do begin
  46.                                 RedX[i] := TempRed[LastColor - i];
  47.                                 GreenX[i] := TempGreen[LastColor - i];
  48.                                 BlueX[i] := TempBlue[LastColor - i];
  49.                             end;
  50.                         UpdateColors;
  51.                     end
  52.                 else begin
  53.                         TempTable := cTable;
  54.                         for i := 1 to 254 do
  55.                             cTable[i] := TempTable[255 - i];
  56.                         LoadLUT(cTable);
  57.                     end;
  58.             end; {with}
  59.     end;
  60.  
  61.  
  62.     procedure UpdateOptionsMenu;
  63.         var
  64.             CheckIt: boolean;
  65.             i: integer;
  66.     begin
  67.         case info^.LUTMode of
  68.             GrayScale, CustomGrayscale: 
  69.                 CheckOnOffItem(OptionsMenuH, 5, 5, 8);
  70.             ColorPalette: 
  71.                 CheckOnOffItem(OptionsMenuH, 6, 5, 8);
  72.             AppleDefault: 
  73.                 CheckOnOffItem(OptionsMenuH, 7, 5, 8);
  74.             Spectrum: 
  75.                 CheckOnOffItem(OptionsMenuH, 8, 5, 8);
  76.             Custom: 
  77.                 for i := 5 to 8 do
  78.                     CheckItem(OptionsMenuH, i, false);
  79.         end;
  80.         SetMenuItem(OptionsMenuH, 12, info <> NoInfo);
  81.         CheckIt := Info^.ScaleToFitWindow;
  82.         CheckItem(OptionsMenuH, 12, CheckIt);
  83.         CheckItem(OptionsMenuH, 13, Thresholding);
  84.     end;
  85.  
  86.  
  87.     procedure UpdateFunctionsMenu;
  88.         var
  89.             ShowItems: boolean;
  90.             i: integer;
  91.     begin
  92.         ShowItems := Info <> NoInfo;
  93.         for i := SmoothItem to ConvolveItem do
  94.             SetMenuItem(FunctionsMenuH, i, ShowItems);
  95.         for i := PhotoModeItem to ChangeItem do
  96.             SetMenuItem(FunctionsMenuH, i, ShowItems);
  97.         with info^ do begin
  98.                 SetMenuItem(FunctionsMenuH, SortItem, (LutMode = custom) or (LutMode = spectrum));
  99.                 SetMenuItem(FunctionsMenuH, UnZoomItem, ShowItems and ((magnification <> 1.0) or ScaleToFitWindow));
  100.             end;
  101.         SetMenuItem(FunctionsMenuH, SetVideoItem, FrameGrabber <> NoFrameGrabber);
  102.     end;
  103.  
  104.  
  105.     procedure SetNumberOfColors;
  106.         var
  107.             TempNColors: integer;
  108.     begin
  109.         TempNColors := GetInt('Number Of Colors(1..32):', info^.ncolors);
  110.         if (TempNColors <= 32) and (TempNColors > 0) then begin
  111.                 info^.nColors := TempNColors;
  112.                 CheckColorWidth;
  113.                 UpdateColors;
  114.             end
  115.         else if TempNColors <> -MaxInt then
  116.             beep;
  117.     end;
  118.  
  119.  
  120.     procedure SetNumberOfExtraColors;
  121.         var
  122.             TempNColors: integer;
  123.     begin
  124.         TempNColors := GetInt('Number Of ExtraColors(0..6):', nExtraColors);
  125.         if (TempNColors <= 6) and (TempNColors >= 0) then begin
  126.                 nExtraColors := TempNColors;
  127.                 RedrawCLUTWindow;
  128.             end
  129.         else if TempNColors <> -MaxInt then
  130.             beep;
  131.     end;
  132.  
  133.  
  134.     procedure ChangeColor;
  135.   {Changes all the pixels in the current selection from the foreground}
  136. {   color(index) to the background color(index).}
  137.         var
  138.             i, value: integer;
  139.             table: LookupTable;
  140.     begin
  141.         for i := 0 to 255 do begin
  142.                 value := i;
  143.                 if value = ForegroundColor then
  144.                     value := BackgroundColor;
  145.                 table[i] := value;
  146.             end;
  147.         ApplyTable(table);
  148.     end;
  149.  
  150.  
  151.     function AboutFilter (d: DialogPtr; var event: EventRecord; var ItemHit: integer): boolean;
  152. { simple filter proc for about box -- must be at top level! % }
  153.     begin
  154.         if (event.what in [MouseDown, KeyDown, AutoKey]) then begin
  155.                 AboutFilter := true;
  156.                 ItemHit := OK;
  157.             end
  158.         else begin
  159.                 AboutFilter := false;
  160.                 ItemHit := 0;
  161.             end;
  162.     end;
  163.  
  164.  
  165.     procedure AboutUProc (d: DialogPtr; item: integer);
  166. { About box user proc -- must be at top level!}
  167.         var
  168.             s: str255;
  169.             saveport: grafptr;
  170.             VersInfo: str255;
  171.     begin
  172.         getport(saveport);
  173.         setport(d);
  174.         if (item = MemItem) then begin
  175.                 NumToString(FreeMem div 1024, s);
  176.                 s := concat(s, 'K free');
  177.                 DrawSItem(MemItem, Geneva, 9, d, s);
  178.             end
  179.         else if (item = VersItem) then begin
  180.                 RealToString(version / 100.0, 4, 2, VersInfo);
  181.                 VersInfo := concat('Version ', VersInfo);
  182.                 DrawSItem(VersItem, Geneva, 9, d, VersInfo);
  183.             end;
  184.         setport(saveport);
  185.     end;
  186.  
  187.  
  188.     procedure DoAbout;
  189.   {About Box by David Powell}
  190.         var
  191.             i: integer;
  192.             d: dialogptr;
  193.             midscreen: point;
  194.             saveport: grafptr;
  195.             r: rect;
  196.             h: handle;
  197.             itype: integer;
  198.     begin
  199.         getport(saveport);
  200.         d := getnewdialog(AboutID, nil, pointer(-1));
  201.         if (d <> nil) then begin
  202.                 SetPort(d);
  203.                 GetDItem(d, VersItem, itype, h, r);
  204.                 SetDItem(d, VersItem, itype, @AboutUProc, r);
  205.                 GetDItem(d, MemItem, itype, h, r);
  206.                 SetDItem(d, MemItem, itype, @AboutUProc, r);
  207.                 ShowWindow(d);
  208.                 repeat
  209.                     ModalDialog(@aboutfilter, i);
  210.                 until (i = OK);
  211.                 DisposDialog(d);
  212.                 FlushEvents(EveryEvent, 0);
  213.             end;
  214.         setport(saveport);
  215.     end;
  216.  
  217.  
  218.     procedure DoMoreOptions;
  219.         const
  220.             WidthID = 4;
  221.             HeightID = 6;
  222.             FramesID = 8;
  223.             InvertID = 9;
  224.             BufferSizeID = 10;
  225.             MaxScionWidthID = 14;
  226.             WandAutoMeasureID = 16;
  227.             WandAutoNumberID = 17;
  228.         var
  229.             mylog: DialogPtr;
  230.             item, i: integer;
  231.             SaveInvert, SaveWandMeasure, SaveWandNumber: boolean;
  232.             SaveWidth, SaveHeight, SaveFrames, SaveMaxWidth: integer;
  233.             SaveBufferSize: LongInt;
  234.     begin
  235.         InitCursor;
  236.         SaveWidth := NewPicWidth;
  237.         SaveHeight := NewPicHeight;
  238.         SaveFrames := nFrames;
  239.         SaveInvert := InvertVideo;
  240.         SaveBufferSize := BufferSize;
  241.         SaveMaxWidth := MaxScionWidth;
  242.         SaveWandMeasure := WandAutoMeasure;
  243.         SaveWandNumber := WandAutoNumber;
  244.         mylog := GetNewDialog(6000, nil, pointer(-1));
  245.         SetDNum(MyLog, WidthID, NewPicWidth);
  246.         SetDNum(MyLog, HeightID, NewPicHeight);
  247.         SetDNum(MyLog, FramesID, nFrames);
  248.         SetDNum(MyLog, BufferSizeID, BufferSize div 1024);
  249.         SetDNum(MyLog, MaxScionWidthID, MaxScionWidth);
  250.         if InvertVideo then
  251.             SetDialogItem(mylog, InvertID, 1);
  252.         if WandAutoMeasure then
  253.             SetDialogItem(mylog, WandAutoMeasureID, 1);
  254.         if WandAutoNumber then
  255.             SetDialogItem(mylog, WandAutoNumberID, 1);
  256.         OutlineButton(MyLog, ok, 16);
  257.         repeat
  258.             ModalDialog(nil, item);
  259.             if item = WidthID then begin
  260.                     NewPicWidth := GetDNum(MyLog, WidthID);
  261.                     if (NewPicWidth < 0) or (NewPicWidth > 2048) then begin
  262.                             NewPicWidth := SaveWidth;
  263.                             SetDNum(MyLog, WidthID, NewPicWidth);
  264.                         end;
  265.                 end;
  266.             if item = HeightID then begin
  267.                     NewPicHeight := GetDNum(MyLog, HeightID);
  268.                     if (NewPicHeight < 0) or (NewPicHeight > 2048) then begin
  269.                             NewPicHeight := SaveHeight;
  270.                             SetDNum(MyLog, HeightID, NewPicHeight);
  271.                         end;
  272.                 end;
  273.             if item = FramesID then begin
  274.                     nFrames := GetDNum(MyLog, FramesID);
  275.                     if (nFrames < 0) or (nFrames > 128) then begin
  276.                             nFrames := SaveFrames;
  277.                             SetDNum(MyLog, FramesID, nFrames);
  278.                         end;
  279.                 end;
  280.             if item = InvertID then begin
  281.                     StopDigitizing;
  282.                     InvertVideo := not InvertVideo;
  283.                     SetDialogItem(mylog, InvertID, ord(InvertVideo));
  284.                 end;
  285.             if item = WandAutoMeasureID then begin
  286.                     WandAutoMeasure := not WandAutoMeasure;
  287.                     SetDialogItem(mylog, WandAutoMeasureID, ord(WandAutoMeasure));
  288.                 end;
  289.             if item = WandAutoNumberID then begin
  290.                     WandAutoNumber := not WandAutoNumber;
  291.                     SetDialogItem(mylog, WandAutoNumberID, ord(WandAutoNumber));
  292.                 end;
  293.             if item = BufferSizeID then begin
  294.                     BufferSize := GetDNum(MyLog, BufferSizeID) * 1024;
  295.                     if BufferSize < 1 then begin
  296.                             beep;
  297.                             BufferSize := 1;
  298.                             SetDNum(MyLog, BufferSizeID, BufferSize);
  299.                         end;
  300.                 end;
  301.             if item = MaxScionWidthID then begin
  302.                     MaxScionWidth := BitAnd(GetDNum(MyLog, MaxScionWidthID), $fffc);
  303.                     if (MaxScionWidth < 0) or (MaxScionWidth > 640) then begin
  304.                             beep;
  305.                             MaxScionWidth := SaveMaxWidth;
  306.                             SetDNum(MyLog, MaxScionWidthID, MaxScionWidth);
  307.                         end;
  308.                 end;
  309.         until (item = ok) or (item = cancel);
  310.         DisposDialog(mylog);
  311.         if NewPicWidth < 32 then
  312.             NewPicWidth := 32;
  313.         if odd(NewPicWidth) then
  314.             NewPicWidth := NewPicWidth + 1;
  315.         if NewPicHeight < 32 then
  316.             NewPicHeight := 32;
  317.         if nFrames < 2 then
  318.             nFrames := 2;
  319.         if item = cancel then begin
  320.                 NewPicWidth := SaveWidth;
  321.                 NewPicHeight := SaveHeight;
  322.                 nFrames := SaveFrames;
  323.                 InvertVideo := SaveInvert;
  324.                 BufferSize := SaveBufferSize;
  325.                 MaxScionWidth := SaveMaxWidth;
  326.                 WandAutoMeasure := SaveWandMeasure;
  327.                 WandAutoNumber := SaveWandNumber;
  328.             end;
  329.         if BufferSize <> SaveBufferSIze then
  330.             PutMessage('You must "Record Preferences" and restart before the Undo and Clipboard buffer ', 'size change will take effect.', '');
  331.     end;
  332.  
  333.  
  334.     procedure CheckWindowsMenuItem;
  335.         var
  336.             i, kind: integer;
  337.             fwptr: WindowPtr;
  338.     begin
  339.         SetMenuItem(WindowsMenuH, 1, nPics > 1);
  340.         for i := 3 to 9 do
  341.             CheckItem(WindowsMenuH, i, false);
  342.         for i := 1 to nPics do
  343.             CheckItem(WindowsMenuH, nItems + i, false);
  344.         fwptr := FrontWindow;
  345.         kind := WindowPeek(fwptr)^.WindowKind;
  346.         if kind < 0 then
  347.             exit(CheckWindowsMenuItem); {System Window}
  348.         case kind of
  349.             ToolKind: 
  350.                 CheckItem(WindowsMenuH, 3, true);
  351.             GrayMapKind: 
  352.                 CheckItem(WindowsMenuH, 4, true);
  353.             LUTKind: 
  354.                 CheckItem(WindowsMenuH, 5, true);
  355.             ResultsKind: 
  356.                 CheckItem(WindowsMenuH, 6, true);
  357.             HistoKind: 
  358.                 CheckItem(WindowsMenuH, 7, true);
  359.             ProfilePlotKind, CalibrationPLotKind: 
  360.                 CheckItem(WindowsMenuH, 8, true);
  361.             PasteControlKind: 
  362.                 CheckItem(WindowsMenuH, 9, true);
  363.             PicKind: 
  364.                 begin
  365.                     i := info^.PicNum;
  366.                     if i > MaxPicsInMenu then
  367.                         i := MaxPicsInMenu;
  368.                     CheckItem(WindowsMenuH, nItems + i, true);
  369.                 end;
  370.             otherwise
  371.         end;
  372.     end;
  373.  
  374.  
  375.     procedure DoClose;
  376.         var
  377.             ignore: integer;
  378.             fwptr: WindowPtr;
  379.             kind: integer;
  380.     begin
  381.         fwptr := FrontWindow;
  382.         kind := WindowPeek(fwptr)^.WindowKind;
  383.         if (kind = PicKind) or (kind = ProfilePlotKind) or (kind = CalibrationPlotKind) or (kind = HistoKind) or (Kind = PasteControlKind) then begin
  384.                 StopDigitizing;
  385.                 ignore := CloseAWindow(fwptr);
  386.             end;
  387.     end;
  388.  
  389.  
  390.     procedure ShowNextWindow;
  391.         var
  392.             n: integer;
  393.     begin
  394.         n := info^.PicNum + 1;
  395.         if n > nPics then
  396.             n := 1;
  397.         SelectWindow(PicWindow[n]);
  398.     end;
  399.  
  400.  
  401.     procedure DoMenuEvent (MenuChoice: LongInt);
  402.         var
  403.             MenuID, MenuItem, i, ignore: integer;
  404.             name, str: str255;
  405.             dna: integer;
  406.             ItemName: str255;
  407.             FontName: str255;
  408.             ok, isSelection: boolean;
  409.             NewStyle: StyleItem;
  410.     begin
  411.         MenuID := HiWord(MenuChoice);
  412.         MenuItem := LoWord(MenuChoice);
  413.         case MenuID of
  414.  
  415.             AppleMenu: 
  416.                 begin
  417.                     if MenuItem = 1 then
  418.                         DoAbout
  419.                     else begin
  420.                             GetItem(GetMHandle(AppleMenu), MenuItem, name);
  421.                             ignore := OpenDeskAcc(name)
  422.                         end;
  423.                 end;
  424.  
  425.             FileMenu: 
  426.                 begin
  427.                     with info^ do
  428.                         isSelection := RoiShowing and (RoiType = RectRoi);
  429.                     case MenuItem of
  430.                         1: 
  431.                             begin
  432.                                 ok := NewPicWindow('Untitled', NewPicWidth, NewPicHeight);
  433.                                 if info^.PicSize > UndoBufSize then
  434.                                     PutWarning;
  435.                             end;
  436.                         2: 
  437.                             begin
  438.                                 StopDigitizing;
  439.                                 GetFile;
  440.                             end;
  441.                         3: 
  442.                             ImportFile;
  443.                         4: 
  444.                             DoClose;
  445.        {5:-}
  446.                         6: 
  447.                             if info^.PictureType <> Camera then {save}
  448.                                 SaveFile
  449.                             else begin
  450.                                     StopDigitizing;
  451.                                     SaveCameraWindow;
  452.                                 end;
  453.                         7: 
  454.                             if isSelection then  {save as TIFF}
  455.                                 SaveSelection(false)
  456.                             else if info^.PictureType <> camera then
  457.                                 SaveTiffAs(0, 0, false)
  458.                             else begin
  459.                                     StopDigitizing;
  460.                                     SaveCameraWindow;
  461.                                 end;
  462.                         8: 
  463.                             if isSelection then
  464.                                 SavePICTAs(true)
  465.                             else
  466.                                 SavePICTAs(false);
  467.                         9: 
  468.                             SaveSettings;
  469.        {10:-}
  470.                         11: 
  471.                             RevertToSaved;
  472.                         12: 
  473.                             begin
  474.                                 StopDigitizing;
  475.                                 Duplicate(false);
  476.                             end;
  477.                         13: 
  478.                             GetInfo;
  479.        {14:-}
  480.                         15: 
  481.                             SetHalftone;
  482.                         16: 
  483.                             DoPageSetup;
  484.                         17: 
  485.                             Print(true);
  486.        {18:-}
  487.                         19: 
  488.                             begin
  489.                                 SavingOutline := true;
  490.                                 SavePICTAs(false);
  491.                             end;
  492.                         20: 
  493.                             SavePalette;
  494.        {21:-}
  495.                         22: 
  496.                             finished := true;
  497.                     end;
  498.                 end;
  499.  
  500.             EditMenu: 
  501.                 begin
  502.                     GetItem(GetMHandle(EditMenu), MenuItem, ItemName);
  503.                     if not SystemEdit(MenuItem - 1) then
  504.                         case MenuItem of
  505.                             1: 
  506.                                 if info <> NoInfo then begin
  507.                                         case WhatToUndo of
  508.                                             UndoMeasurement: 
  509.                                                 UndoLastMeasurement;
  510.                                             UndoContrastEnhancement, UndoEqualization: 
  511.                                                 begin
  512.                                                     ResetGrayMap;
  513.                                                     WhatToUndo := NothingToUndo;
  514.                                                 end;
  515.                                             UndoZoom: 
  516.                                                 begin
  517.                                                     DeZoom;
  518.                                                     if info^.magnification < 2 then
  519.                                                         WhatToUndo := NothingToUndo;
  520.                                                 end;
  521.                                             UndoOutLine: 
  522.                                                 begin
  523.                                                     undo;
  524.                                                     if WandAutoMeasure then
  525.                                                         UndoLastMeasurement;
  526.                                                     WhatToUndo := NothingToUndo;
  527.                                                     UpdatePicWindow;
  528.                                                 end;
  529.                                             otherwise
  530.                                                 begin
  531.                                                     if UndoFromClip then
  532.                                                         OpPending := false;
  533.                                                     if not OpPending then
  534.                                                         undo;
  535.                                                     WhatToUndo := NothingToUndo;
  536.                                                     if IsInsertionPoint then begin
  537.                                                             InsertionPoint := TextStart;
  538.                                                             TextStr := '';
  539.                                                         end;
  540.                                                     UpdatePicWindow;
  541.                                                     if OpPending and (CurrentOp = PasteOp) then begin
  542.                                                             OpPending := false;
  543.                                                             KillRoi;
  544.                                                         end;
  545.                                                     OpPending := false;
  546.                                                 end;
  547.                                         end; {case}
  548.                                     end;
  549.        {2:-}
  550.                             3: 
  551.                                 DoCut;
  552.                             4: 
  553.                                 DoCopy;
  554.                             5: 
  555.                                 begin
  556.                                     StopDigitizing;
  557.                                     DoPaste
  558.                                 end;
  559.                             6: 
  560.                                 DoClear;
  561.       {7:---}
  562.                             8, 9, 10: 
  563.                                 SetupOperation(MenuItem);
  564.        {11:-}
  565.                             12: 
  566.                                 if PasteControl = nil then
  567.                                     ShowPasteControl
  568.                                 else
  569.                                     BringToFront(PasteControl);
  570.                             13: 
  571.                                 begin
  572.                                     StopDigitizing;
  573.                                     SelectAll(true)
  574.                                 end;
  575.                             14: 
  576.                                 ScaleSelection;
  577.        {15:-}
  578.                             16: 
  579.                                 FlipOrRotate(RotateLeft);
  580.                             17: 
  581.                                 FlipOrRotate(RotateRight);
  582.                             18: 
  583.                                 FlipOrRotate(FlipVertical);
  584.                             19: 
  585.                                 FlipOrRotate(FlipHorizontal);
  586.                             20: 
  587.                                 RotateAndScale;
  588.       {21:---}
  589.                             22: 
  590.                                 ShowClipboard;
  591.                         end;
  592.                 end;
  593.  
  594.             OptionsMenu: 
  595.                 begin
  596.                     case MenuItem of
  597.                         1: 
  598.                             InvertPalette;
  599.                         2: 
  600.                             SetNumberOfColors;
  601.                         3: 
  602.                             SetNumberOfExtraColors;
  603.        {4:---}
  604.                         5: 
  605.                             ResetGrayMap;
  606.                         6: 
  607.                             UpdateColors;
  608.                         7: 
  609.                             ok := LoadCLUTResource(AppleDefaultCLUT);
  610.                         8: 
  611.                             Load256ColorCLUT;
  612.        {9:---}
  613.                         10: 
  614.                             DoProfilePlotOptions;
  615.                         11: 
  616.                             DoMoreOptions;
  617.                         12: 
  618.                             ScaleToFit;
  619.                         13: 
  620.                             if Thresholding then
  621.                                 StopThresholding
  622.                             else
  623.                                 StartThresholding;
  624.                     end;
  625.                 end;
  626.  
  627.             FunctionsMenu: 
  628.                 begin
  629.                     SetupUndo;
  630.                     case MenuItem of
  631.                         SmoothItem: 
  632.                             if OptionKeyDown then
  633.                                 Filter(UnweightedAvg, true)
  634.                             else
  635.                                 Filter(WeightedAvg, true);
  636.                         SharpenItem: 
  637.                             Filter(fsharpen, true);
  638.                         EdgeDetectItem: 
  639.                             Filter(EdgeDetect, true);
  640.                         ReduceNoiseItem: 
  641.                             Filter(ReduceNoise, true);
  642.                         DitherItem: 
  643.                             Filter(Dither, true);
  644.                         ConvolveItem: 
  645.                             Convolve;
  646.        {---}
  647.                         PhotoModeItem: 
  648.                             PhotoMode;
  649.                         AnimateItem: 
  650.                             Animate;
  651.                         EnhanceItem: 
  652.                             EnhanceContrast;
  653.                         EqualizeItem: 
  654.                             EqualizeHistogram;
  655.                         ApplyItem: 
  656.                             ApplyLookupTable;
  657.                         ChangeItem: 
  658.                             ChangeColor;
  659.                         SortItem: 
  660.                             SortPalette;
  661.                         UnZoomItem: 
  662.                             Unzoom;
  663.        {--}
  664.                         StartItem: 
  665.                             StartDigitizing;
  666.                         AverageItem: 
  667.                             AverageFrames;
  668.                         SetVideoItem: 
  669.                             SetVideoChannel;
  670.                     end;
  671.                 end;
  672.  
  673.             BinaryMenu: 
  674.                 case MenuItem of
  675.                     MakeBinaryItem: 
  676.                         MakeBinary;
  677.                     ErosionItem: 
  678.                         filter(Erosion, true);
  679.                     DilationItem: 
  680.                         filter(Dilation, true);
  681.                     OpeningItem: 
  682.                         begin
  683.                             filter(Erosion, true);
  684.                             filter(Dilation, false);
  685.                         end;
  686.                     ClosingItem: 
  687.                         begin
  688.                             filter(Dilation, true);
  689.                             filter(Erosion, false);
  690.                         end;
  691.                     OutlineItem: 
  692.                         filter(OutlineFilter, true);
  693.                     SkeletonizeItem: 
  694.                         MakeSkeleton;
  695.                 end;
  696.  
  697.             AnalysisMenu: 
  698.                 begin
  699.                     SetupUndo;
  700.                     case MenuItem of
  701.                         MeasureItem: 
  702.                             Measure;
  703.                         ShowItem: 
  704.                             ListResults;
  705.                         OptionsItem: 
  706.                             DoMeasurementOptions;
  707.                         HistogramItem: 
  708.                             DoHistogram;
  709.                         PlotItem: 
  710.                             ColumnAveragePlot;
  711.                         Plot3DItem: 
  712.                             Do3DPlot;
  713.        {---}
  714.                         SaveBlankFieldItem: 
  715.                             SaveBlankField;
  716.                         SetScaleItem: 
  717.                             SetScale;
  718.                         CalibrateItem: 
  719.                             Calibrate;
  720.                         ResetItem: 
  721.                             ResetCounters;
  722.                         RestoreItem: 
  723.                             begin
  724.                                 StopDigitizing;
  725.                                 RestoreRoi;
  726.                             end;
  727.                         NumberSelectionItem: 
  728.                             NumberSelection(nAreas);
  729.                     end;
  730.                 end;
  731.  
  732.             TextMenu: 
  733.                 begin
  734.                     case MenuItem of
  735.                         LeftItem: 
  736.                             TextJust := LeftJust;
  737.                         CenterItem: 
  738.                             TextJust := CenterJust;
  739.                         RightItem: 
  740.                             TextJust := RightJust;
  741.                         NoBackgroundItem: 
  742.                             TextBack := NoBack;
  743.                         WithBackgroundItem: 
  744.                             TextBack := WithBack;
  745.                     end;
  746.                     DisplayText;
  747.                     if IsInsertionPoint then
  748.                         UpdatePicWindow;
  749.                     UpdateTextMenu;
  750.                 end;
  751.  
  752.             FontMenu: 
  753.                 begin
  754.                     GetItem(FontMenuH, MenuItem, FontName);
  755.                     GetFNum(FontName, CurrentFontID);
  756.                     UpdateTextMenu;
  757.                     DisplayText;
  758.                 end;
  759.  
  760.             SizeMenu: 
  761.                 begin
  762.                     case MenuItem of
  763.                         1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11: 
  764.                             CurrentSize := GetFontSize(MenuItem);
  765.                     end;
  766.                     DisplayText;
  767.                     if IsInsertionPoint then
  768.                         UpdatePicWindow;
  769.                     UpdateTextMenu;
  770.                 end;
  771.  
  772.             StyleMenu: 
  773.                 begin
  774.                     case MenuItem of
  775.                         1: 
  776.                             CurrentStyle := [];
  777.                         2, 3, 4, 5, 6: 
  778.                             begin
  779.                                 case MenuItem of
  780.                                     TxBold: 
  781.                                         NewStyle := Bold;
  782.                                     TxItalic: 
  783.                                         NewStyle := Italic;
  784.                                     TxUnderLine: 
  785.                                         NewStyle := Underline;
  786.                                     TxOutLine: 
  787.                                         NewStyle := Outline;
  788.                                     TxShadow: 
  789.                                         NewStyle := Shadow;
  790.                                 end;
  791.                                 if NewStyle in CurrentStyle then
  792.                                     CurrentStyle := CurrentStyle - [NewStyle]
  793.                                 else
  794.                                     CurrentStyle := CurrentStyle + [NewStyle];
  795.                             end;
  796.          {7:--}
  797.                         8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18: 
  798.                             CurrentSize := GetFontSize(MenuItem);
  799.                     end; {case}
  800.                     DisplayText;
  801.                     if IsInsertionPoint then
  802.                         UpdatePicWindow;
  803.                     UpdateTextMenu;
  804.                 end;
  805.  
  806.             WindowsMenu: 
  807.                 begin
  808.                     case MenuItem of
  809.                         1: 
  810.                             ShowNextWindow;
  811.                         3: 
  812.                             SelectWindow(ToolWindow);
  813.                         4: 
  814.                             SelectWindow(GrayMapWindow);
  815.                         5: 
  816.                             SelectWindow(LUTWindow);
  817.                         6: 
  818.                             SelectWindow(ResultsWindow);
  819.                         7: 
  820.                             if HistoWindow <> nil then
  821.                                 SelectWindow(HistoWindow);
  822.                         8: 
  823.                             if PlotWindow <> nil then
  824.                                 SelectWindow(PlotWindow);
  825.                         9: 
  826.                             if PasteControl <> nil then
  827.                                 SelectWindow(PasteControl);
  828.                         10: 
  829.                             ; {--}
  830.                         otherwise
  831.                             SelectWindow(PicWindow[MenuItem - NItems]);
  832.                     end;
  833.                 end;
  834.             UserMenu: 
  835.                 DoUserMenuEvent(MenuItem);
  836.             otherwise
  837.         end;
  838.         HiliteMenu(0);
  839.     end;
  840.  
  841.  
  842.     procedure DoFreehand (var nVertices: integer; ff: integer; var x, y: xyArray);
  843.         var
  844.             finish: point;
  845.             event: EventRecord;
  846.             wright, wbottom: integer;
  847.     begin
  848.         PenPat(pat[PatIndex]);
  849.         with info^.wptr^.PortRect do begin
  850.                 wright := right;
  851.                 wbottom := bottom;
  852.             end;
  853.         repeat
  854.             GetMouse(finish);
  855.             with finish do begin
  856.                     if h < 0 then
  857.                         h := 0;
  858.                     if v < 0 then
  859.                         v := 0;
  860.                     if h > wright then
  861.                         h := wright;
  862.                     if v > wbottom then
  863.                         v := wbottom;
  864.                 end;
  865.             if nvertices < MaxPolyVertices then
  866.                 nvertices := nvertices + 1
  867.             else
  868.                 beep;
  869.             with finish do begin
  870.                     LineTo(h - ff, v - ff);
  871.                     x[nvertices] := h;
  872.                     y[nvertices] := v;
  873.                 end;
  874.             ticks := TickCount + 4;
  875.             repeat
  876.             until TickCount >= ticks;
  877.         until GetNextEvent(mUpMask, Event);
  878.     end;
  879.  
  880.  
  881.     procedure MakePolygon (event: EventRecord);
  882.         var
  883.             Start, Finish, OldFinish, StartingPoint, pt, p1, p2, spt: point;
  884.             r, StartRect, tRect: rect;
  885.             tPort: GrafPtr;
  886.             ticks, MouseUpTime, LastMouseUpTime: LongInt;
  887.             finished, DoubleClick: boolean;
  888.             nvertices, i, ff, wright, wbottom, imag: integer;
  889.             x, y: xyArray;
  890.             TempRgn: RgnHandle;
  891.     begin
  892.         if SelectionMode <> NewSelection then
  893.             TempRgn := NewRgn;
  894.         start := event.where;
  895.         StartingPoint := start;
  896.         Pt2Rect(start, start, StartRect);
  897.         with Info^ do begin
  898.                 imag := trunc(magnification + 0.5);
  899.                 ff := imag div 2;
  900.                 if ff < 1 then
  901.                     ff := 1;
  902.                 InsetRect(StartRect, -4 * ff, -4 * ff);
  903.                 PenNormal;
  904.                 if CurrentTool = PolygonTool then begin
  905.                         PenMode(PatXor);
  906.                         FrameRect(StartRect);
  907.                     end;
  908.                 PenSize(imag, imag);
  909.                 finish := start;
  910.                 finished := false;
  911.                 x[1] := StartingPoint.h;
  912.                 y[1] := StartingPoint.v;
  913.                 nvertices := 1;
  914.             end;
  915.         MoveTo(start.h, start.v);
  916.         if CurrentTool = FreehandTool then begin
  917.                 DoFreehand(nVertices, ff, x, y);
  918.                 with StartingPoint do
  919.                     LineTo(h - ff, v - ff);
  920.             end
  921.         else begin   {Draw using polygon tool}
  922.                 with info^.wptr^.PortRect do begin
  923.                         wright := right;
  924.                         wbottom := bottom;
  925.                     end;
  926.                 MouseUpTime := 0;
  927.                 repeat
  928.                     repeat
  929.                         OldFinish := finish;
  930.                         GetMouse(finish);
  931.                         with finish do begin
  932.                                 if h < 0 then
  933.                                     h := 0;
  934.                                 if v < 0 then
  935.                                     v := 0;
  936.                                 if h > wright then
  937.                                     h := wright;
  938.                                 if v > wbottom then
  939.                                     v := wbottom;
  940.                             end;
  941.                         if not EqualPt(finish, OldFinish) then begin
  942.                                 ticks := TickCount;
  943.                                 repeat
  944.                                 until TickCount <> ticks;
  945.                                 MoveTo(start.h - ff, start.v - ff);
  946.                                 LineTo(OldFinish.h - ff, OldFinish.v - ff);
  947.                                 MoveTo(start.h - ff, start.v - ff);
  948.                                 LineTo(finish.h - ff, finish.v - ff);
  949.                             end;
  950.                     until GetNextEvent(mUpMask, Event);
  951.                     LastMouseUpTime := MouseUpTime;
  952.                     MouseUpTime := TickCount;
  953.                     DoubleClick := ((MouseUpTime - LastMouseUpTime) < GetDblTime) and EqualPt(start, finish);
  954.                     if nvertices < MaxPolyVertices then
  955.                         nvertices := nvertices + 1
  956.                     else
  957.                         beep;
  958.                     x[nvertices] := finish.h;
  959.                     y[nvertices] := finish.v;
  960.                     start := finish;
  961.                     Finished := (PtInRect(finish, StartRect) or DoubleClick) and (nvertices > 2);
  962.                 until finished;
  963.             end;
  964.         if nvertices > 2 then
  965.             with Info^ do begin
  966.                     PenNormal;
  967.                     OpenRgn;
  968.                     spt.h := x[1];
  969.                     spt.v := y[1];
  970.                     ScreenToOffscreen(spt);
  971.                     MoveTo(spt.h, spt.v);
  972.                     for i := 2 to nvertices do begin
  973.                             pt.h := x[i];
  974.                             pt.v := y[i];
  975.                             ScreenToOffscreen(pt);
  976.                             LineTo(pt.h, pt.v);
  977.                         end;
  978.                     LineTo(spt.h, spt.v);
  979.                     case SelectionMode of
  980.                         NewSelection: 
  981.                             CloseRgn(osroiRgn);
  982.                         AddSelection: 
  983.                             begin
  984.                                 CloseRgn(TempRgn);
  985.                                 if RgnNotTooBig(osroiRgn, TempRgn) then
  986.                                     UnionRgn(osroiRgn, TempRgn, osroiRgn);
  987.                             end;
  988.                         SubSelection: 
  989.                             begin
  990.                                 CloseRgn(TempRgn);
  991.                                 if RgnNotTooBig(osroiRgn, TempRgn) then
  992.                                     DiffRgn(osroiRgn, TempRgn, osroiRgn);
  993.                             end;
  994.                     end;
  995.                     RoiShowing := true;
  996.                     roiType := RgnRoi;
  997.                     osroiRect := osroiRgn^^.rgnBBox;
  998.                     roiRect := osroiRect;
  999.                     OffscreenToScreenRect(roiRect);
  1000.                     UpdatePicWindow;
  1001.                     if PerimeterM in measurements then
  1002.                         ComputeLength(nvertices, x, y, true)
  1003.                     else
  1004.                         results.Length := 0.0;
  1005.                 end
  1006.         else
  1007.             with info^ do begin
  1008.                     RoiShowing := false;
  1009.                     RoiType := NoRoi;
  1010.                     UpdatePicWindow;
  1011.                 end;
  1012.         if SelectionMode <> NewSelection then
  1013.             DisposeRgn(TempRgn);
  1014.         WhatToUndo := NothingToUndo;
  1015.         measuring := false;
  1016.         repeat
  1017.         until not GetNextEvent(EveryEvent, Event); {FlushEvent doesn't work under A/UX!}
  1018.     end;
  1019.  
  1020.  
  1021.     procedure FindCurveLength (event: EventRecord);
  1022.         var
  1023.             Start, p: point;
  1024.             nvertices, ff, i, imag: integer;
  1025.             x, y: xyArray;
  1026.             tPort: GrafPtr;
  1027.     begin
  1028.         start := event.where;
  1029.         x[1] := start.h;
  1030.         y[1] := start.v;
  1031.         nvertices := 1;
  1032.         PenNormal;
  1033.         with info^ do begin
  1034.                 imag := trunc(magnification + 0.5);
  1035.                 PenSize(imag, imag);
  1036.                 ff := imag div 2
  1037.             end;
  1038.         if ff < 1 then
  1039.             ff := 1;
  1040.         MoveTo(start.h, start.v);
  1041.         DoFreehand(nVertices, ff, x, y);
  1042.         GetPort(tPort);
  1043.         SetPort(GrafPtr(info^.osPort));
  1044.         PenNormal;
  1045.         PenSize(LineWidth, LineWidth);
  1046.         p.h := x[1];
  1047.         p.v := y[1];
  1048.         ScreenToOffscreen(p);
  1049.         MoveTo(p.h, p.v);
  1050.         for i := 2 to nvertices do begin
  1051.                 p.h := x[i];
  1052.                 p.v := y[i];
  1053.                 ScreenToOffscreen(p);
  1054.                 LineTo(p.h, p.v);
  1055.             end;
  1056.         SetPort(tPort);
  1057.         UpdatePicWindow;
  1058.         ComputeLength(nvertices, x, y, false);
  1059.         if nLengths < MaxLengths then begin
  1060.                 nLengths := nLengths + 1;
  1061.                 UnsavedLengths := UnsavedLengths + 1
  1062.             end
  1063.         else
  1064.             beep;
  1065.         with results do begin
  1066.                 PixelLength := length;
  1067.                 lengths[nLengths] := length;
  1068.                 TotalLength := TotalLength + length;
  1069.             end;
  1070.         ShowResults;
  1071.         measuring := true;
  1072.     end;
  1073.  
  1074.  
  1075.     procedure DoMouseDownInWindow (event: EventRecord; WhichWindow: WindowPtr);
  1076.         var
  1077.             r: rect;
  1078.             str: str255;
  1079.             hloc, vloc: integer;
  1080.             tool: ToolType;
  1081.     begin
  1082.         if (WindowPeek(WhichWindow)^.WindowKind <> PicKind) then
  1083.             exit(DoMouseDownInWindow);
  1084.         if Digitizing and isSelectionTool then
  1085.             PasteMode := LiveSelection;
  1086.         if Digitizing then
  1087.             if (CurrentTool <> MagnifyingGlass) and (CurrentTool <> Grabber) then
  1088.                 StopDigitizing;
  1089.         GlobalToLocal(event.where);
  1090.         IsInsertionPoint := false;
  1091.         if MouseState <> NotInRoi then
  1092.             exit(DoMouseDownInWindow);
  1093.         WhatToUndo := UndoEdit;
  1094.         if (SelectionMode = NewSelection) and not ((CurrentTool = MagnifyingGlass) or (CurrentTool = Grabber)) then
  1095.             KillRoi;
  1096.         SetupUndo;
  1097.         if SpaceBarDown and (CurrentTool <> TextTool) then
  1098.             tool := grabber
  1099.         else
  1100.             tool := CurrentTool;
  1101.         case tool of
  1102.             SelectionTool: 
  1103.                 DoObject(SelectionRect, event);
  1104.             OvalSelectionTool: 
  1105.                 DoObject(SelectionOval, event);
  1106.             RoundedRectTool: 
  1107.                 DoObject(RoundedRect, event);
  1108.             MagnifyingGlass: 
  1109.                 Zoom(event);
  1110.             Grabber: 
  1111.                 Scroll(event);
  1112.             Pencil, Brush, Eraser: 
  1113.                 DoBrush(event);
  1114.             AirBrushTool: 
  1115.                 DoAirBrush(event);
  1116.             ruler: 
  1117.                 if OptionKeyDown then
  1118.                     FindCurveLength(event)
  1119.                 else
  1120.                     DoObject(LengthObj, event);
  1121.             PaintBucket: 
  1122.                 AreaFill(event);
  1123.             PolygonTool, FreehandTool: 
  1124.                 MakePolygon(event);
  1125.             TextTool: 
  1126.                 DoText(event.where);
  1127.             PlotTool: 
  1128.                 DoObject(PlotLine, event);
  1129.             PickerTool: 
  1130.                 if BitAnd(Event.modifiers, OptionKey) = OptionKey then
  1131.                     GetBackgroundColor(event)
  1132.                 else
  1133.                     GetForegroundColor(event);
  1134.             PointingTool: 
  1135.                 DoPoints(event);
  1136.             AngleTool: 
  1137.                 FindAngle(event);
  1138.             Wand: 
  1139.                 begin
  1140.                     if Digitizing then
  1141.                         StopDigitizing;
  1142.                     AutoOutline(event.where);
  1143.                 end;
  1144.             otherwise
  1145.                 beep;
  1146.         end;
  1147.     end;
  1148.  
  1149.  
  1150.     procedure DoMouseDownInTools (loc: point);
  1151.         var
  1152.             r: rect;
  1153.             tPort: GrafPtr;
  1154.             OddTool, DoubleClick: boolean;
  1155.             ToolNum, i: integer;
  1156.     begin
  1157.         GetPort(tPort);
  1158.         SetPort(ToolWindow);
  1159.         GlobalToLocal(loc);
  1160.         if loc.v <= StartOfLines then begin
  1161.                 PreviousTool := CurrentTool;
  1162.                 OddTool := loc.h < tmiddle;
  1163.                 ToolNum := (loc.v div tmiddle) * 2;
  1164.                 if not OddTool then
  1165.                     ToolNum := ToolNum + 1;
  1166.                 CurrentTool := ToolType(ToolNum);
  1167.                 isSelectionTool := (CurrentTool = SelectionTool) or (CurrentTool = OvalSelectionTool) or (CurrentTool = PolygonTool) or (CurrentTool = FreehandTool) or (CurrentTool = RoundedRectTool);
  1168.                 DoubleClick := (TickCount - ToolTime) < GetDblTime;
  1169.                 ToolTime := TickCount;
  1170.                 InvalRect(ToolRect[CurrentTool]);
  1171.                 InvalRect(ToolRect[PreviousTool]);
  1172.                 IsInsertionPoint := false;
  1173.                 if DoubleClick and (CurrentTool = PreviousTool) then
  1174.                     case CurrentTool of
  1175.                         MagnifyingGlass: 
  1176.                             Unzoom;
  1177.                         SelectionTool: 
  1178.                             begin
  1179.                                 StopDigitizing;
  1180.                                 SelectAll(true);
  1181.                             end;
  1182.                         AirbrushTool: 
  1183.                             SetAirbrushSize;
  1184.                         Brush: 
  1185.                             SetBrushSize;
  1186.                         ruler: 
  1187.                             SetScale;
  1188.                         PolygonTool: 
  1189.                             DoMeasurementOptions;
  1190.                         FreehandTool: 
  1191.                             Calibrate;
  1192.                         PlotTool: 
  1193.                             DoProfilePlotOptions;
  1194.                         eraser: 
  1195.                             if info <> NoInfo then begin
  1196.                                     KillRoi;
  1197.                                     WhatToUndo := UndoClear;
  1198.                                     SetupUndo;
  1199.                                     StopDigitizing;
  1200.                                     SelectAll(false);
  1201.                                     DoOperation(eraseOp);
  1202.                                 end;
  1203.                         LutTool, Wand: 
  1204.                             if Thresholding then
  1205.                                 StopThresholding
  1206.                             else
  1207.                                 StartThresholding;
  1208.                         PickerTool: 
  1209.                             if info^.LutMode <> ColorPalette then begin  {Switch to pseudocolor mode}
  1210.                                     StopThresholding;
  1211.                                     UpdateColors;
  1212.                                     CurrentTool := LutTool;
  1213.                                     InvalRect(ToolRect[CurrentTool]);
  1214.                                 end
  1215.                             else
  1216.                                 ResetGrayMap;
  1217.                         otherwise
  1218.                     end; {case}
  1219.                 if (not isSelectionTool) and (CurrentTool <> MagnifyingGlass) and (CurrentTool <> Grabber) then
  1220.                     KillRoi;
  1221.                 if (CurrentTool = SelectionTool) or (CurrentTool = ruler) or (CurrentTool = PointingTool) then
  1222.                     ShowResults;
  1223.                 StretchMode := false;
  1224.             end
  1225.         else begin
  1226.                 for i := 1 to nLineTypes do begin
  1227.                         r := lines[i];
  1228.                         with r do begin
  1229.                                 left := left - 13;
  1230.                                 top := top - 2;
  1231.                                 right := right + 2;
  1232.                                 bottom := bottom + 2;
  1233.                             end;
  1234.                         if i = 1 then
  1235.                             with r do
  1236.                                 top := top - 7;
  1237.                         if PtInRect(loc, r) then begin
  1238.                                 with lines[i] do
  1239.                                     LineWidth := bottom - top;
  1240.                                 LineIndex := i;
  1241.                             end;
  1242.                     end;
  1243.                 EraseRect(CheckRect);
  1244.                 InvalRect(CheckRect);
  1245.             end;
  1246.         SetPort(tPort);
  1247.     end;
  1248.  
  1249.  
  1250.     procedure RotateColors;
  1251.         var
  1252.             tPort: GrafPtr;
  1253.             vstart, i, j, delta: integer;
  1254.             loc: point;
  1255.             TempTable: MyCSpecArray;
  1256.     begin
  1257.         with info^ do begin
  1258.                 getPort(tPort);
  1259.                 SetPort(LUTWindow);
  1260.                 GetMouse(loc);
  1261.                 vstart := loc.v;
  1262.                 repeat
  1263.                     GetMouse(loc);
  1264.                     delta := vstart - loc.v;
  1265.                     for i := 1 to 254 do begin {0 is resevred for white and 255 for black}
  1266.                             j := i + delta;
  1267.                             if j > 254 then
  1268.                                 j := j - 254;
  1269.                             if j > 254 then
  1270.                                 j := 254;
  1271.                             if j < 1 then
  1272.                                 j := j + 254;
  1273.                             if j < 1 then
  1274.                                 j := 1;
  1275.                             TempTable[i] := cTable[j]
  1276.                         end;
  1277.                     cTable := TempTable;
  1278.                     LoadLUT(cTable);
  1279.                     vstart := loc.v;
  1280.                 until not button;
  1281.                 SetPort(tPort);
  1282.             end;
  1283.     end;
  1284.  
  1285.  
  1286.     procedure UpdateThreshold;
  1287.         var
  1288.             tPort: GrafPtr;
  1289.             loc: point;
  1290.             vloc, ThresholdWidth, SaveVLoc, delta: integer;
  1291.             UpdateStart: boolean;
  1292.             cvalue: extended;
  1293.     begin
  1294.         if (CurrentTool = LutTool) or (CurrentTool = Wand) then begin
  1295.                 ValuesMode := IndexValue;
  1296.                 DrawLabels;
  1297.                 GetPort(tPort);
  1298.                 SetPort(LUTWindow);
  1299.                 GetMouse(loc);
  1300.                 SaveVLoc := loc.v;
  1301.                 if SaveVLoc > 255 then
  1302.                     SaveVLoc := 255;
  1303.                 while button do begin
  1304.                         GetMouse(loc);
  1305.                         vloc := loc.v;
  1306.                         if vloc > 255 then
  1307.                             vloc := 255;
  1308.                         if vloc <= 0 then
  1309.                             vloc := 0;
  1310.                         ThresholdWidth := ThresholdEnd - ThresholdStart + 1;
  1311.                         delta := vloc - SaveVLoc;
  1312.                         SaveVLoc := vloc;
  1313.                         UpdateStart := vloc <= (ThresholdStart + ThresholdWidth div 3);
  1314.                         if UpdateStart then begin
  1315.                                 ThresholdStart := vloc;
  1316.                                 if ThresholdStart < 1 then
  1317.                                     ThresholdStart := 1
  1318.                             end
  1319.                         else begin
  1320.                                 ThresholdEnd := ThresholdEnd + delta;
  1321.                                 if ThresholdEnd > 254 then
  1322.                                     ThresholdEnd := 254;
  1323.                                 ThresholdStart := ThresholdEnd - ThresholdWidth + 1;
  1324.                                 if ThresholdStart < 1 then
  1325.                                     ThresholdStart := 1;
  1326.                             end;
  1327.                         if ThresholdStart > ThresholdEnd then
  1328.                             ThresholdStart := ThresholdEnd;
  1329.                         DrawThreshold;
  1330.                         if UpdateStart then
  1331.                             vloc := ThresholdStart
  1332.                         else
  1333.                             vloc := ThresholdEnd;
  1334.                         if info^.calibrated then
  1335.                             cvalue := value[vloc]
  1336.                         else
  1337.                             cvalue := noValue;
  1338.                         Show1Value(vloc, cvalue)
  1339.                     end;
  1340.                 SetPort(tPort);
  1341.             end
  1342.         else if CurrentTool = PickerTool then
  1343.             EditThresholdColor;
  1344.     end;
  1345.  
  1346.  
  1347.     function GetColorFromPalette (DoubleClick: boolean): integer;
  1348.         var
  1349.             tPort: GrafPtr;
  1350.             mloc, color, i: integer;
  1351.             loc: point;
  1352.     begin
  1353.         getPort(tPort);
  1354.         SetPort(LUTWindow);
  1355.         GetMouse(loc);
  1356.         if loc.v > 255 then begin
  1357.                 color := 0;
  1358.                 for i := 1 to nExtraColors + 2 do
  1359.                     if PtInRect(loc, ExtraColorsRect[i]) then
  1360.                         Color := ExtraColorsEntry[i];
  1361.                 if DoubleClick then
  1362.                     EditExtraColors(color);
  1363.                 GetColorFromPalette := color;
  1364.             end
  1365.         else
  1366.             GetColorFromPalette := loc.v;
  1367.         SetPort(tPort);
  1368.     end;
  1369.  
  1370.  
  1371.     procedure DoMouseDownInLUT (event: EventRecord);
  1372.         var
  1373.             tPort: GrafPtr;
  1374.             loc: point;
  1375.             MidPoint, mloc, i, color: integer;
  1376.             DoubleClick: boolean;
  1377.     begin
  1378.         with info^ do begin
  1379.                 if CurrentTool = PickerTool then
  1380.                     DoubleClick := (TickCount - LutTime) < GetDblTime
  1381.                 else
  1382.                     DoubleClick := false;
  1383.                 LutTime := TickCount;
  1384.                 if (CurrentTool <> LutTool) and (CurrentTool <> Wand) then begin
  1385.                         color := GetColorFromPalette(DoubleClick);
  1386.                         if (CurrentTool = eraser) or OptionKeyDown then
  1387.                             SetBackgroundColor(color)
  1388.                         else
  1389.                             SetForegroundColor(color);
  1390.                         if not DoubleClick then
  1391.                             exit(DoMouseDownInLUT);
  1392.                     end;
  1393.                 if Thresholding then begin
  1394.                         UpdateThreshold;
  1395.                         exit(DoMouseDownInLUT)
  1396.                     end;
  1397.                 if nColors = 0 then
  1398.                     exit(DoMouseDownInLUT);
  1399.                 if (LUTMode <> ColorPalette) and not DoubleClick then begin
  1400.                         if DeltaX <> 0 then
  1401.                             RotateColors;
  1402.                         exit(DoMouseDownInLUT)
  1403.                     end;
  1404.                 if (CurrentTool = PickerTool) and DoubleClick then begin
  1405.                         if LUTMode <> ColorPalette then
  1406.                             exit(DoMouseDownInLUT);
  1407.                         EditColor;
  1408.                         exit(DoMouseDownInLUT)
  1409.                     end;
  1410.                 GetPort(tPort);
  1411.                 SetPort(LUTWindow);
  1412.                 repeat
  1413.                     GetMouse(loc);
  1414.                     if loc.v <= 255 then begin
  1415.                             mloc := 255 - loc.v;
  1416.                             MidPoint := ColorStart + (nColors * ColorWidth) div 2;
  1417.                             if mloc < MidPoint then begin
  1418.                                     ColorStart := mloc;
  1419.                                     if ColorStart < 0 then
  1420.                                         ColorStart := 0
  1421.                                 end
  1422.                             else begin
  1423.                                     ColorWidth := (mloc - ColorStart) div ncolors;
  1424.                                     if ColorWidth < 1 then
  1425.                                         ColorWidth := 1;
  1426.                                 end;
  1427.                             UpdateColors;
  1428.                         end;
  1429.                 until not Button;
  1430.                 SetPort(tPort);
  1431.             end; {with}
  1432.     end;
  1433.  
  1434.  
  1435.     procedure DoZoomIn;
  1436.         var
  1437.             trect: rect;
  1438.             ignore: boolean;
  1439.     begin
  1440.         with info^ do begin
  1441.                 MoveWindow(wptr, PicWindowLeft, PicWindowTop, true);
  1442.                 SetRect(trect, 0, 0, ScreenWidth, ScreenHeight);
  1443.                 ZoomImageWindow(trect);
  1444.                 wrect := trect;
  1445.                 SizeWindow(wptr, trect.right, trect.bottom, true);
  1446.             end;
  1447.     end;
  1448.  
  1449.  
  1450.     procedure DoDrag (WhichWindow: WindowPtr; loc: point);
  1451.         var
  1452.             WinRect, DragBounds: rect;
  1453.             kind: integer;
  1454.     begin
  1455.         kind := WindowPeek(WhichWindow)^.WindowKind;
  1456.         if (kind = PicKind) and (info^.PictureType = ScionType) then
  1457.             exit(DoDrag);
  1458.         DragBounds := ScreenBits.bounds;
  1459.         DragWindow(WhichWindow, loc, DragBounds);
  1460.         if WhichWindow = ResultsWindow then
  1461.             ShowResults;
  1462.     end;
  1463.  
  1464.  
  1465.     procedure FindWhatToPrint;
  1466.         var
  1467.             kind: integer;
  1468.             WhichWindow: WindowPtr;
  1469.     begin
  1470.         WhatToPrint := NothingToPrint;
  1471.         WhichWindow := FrontWindow;
  1472.         kind := WindowPeek(WhichWindow)^.WindowKind;
  1473.         if (kind = PicKind) and info^.RoiShowing and measuring then
  1474.             kind := ResultsKind;
  1475.         case kind of
  1476.             PicKind: 
  1477.                 if info^.RoiShowing then
  1478.                     WhatToPrint := PrintSelection
  1479.                 else
  1480.                     WhatToPRint := PrintImage;
  1481.             HistoKind: 
  1482.                 WhatToPrint := PrintHistogram;
  1483.             ProfilePlotKind, CalibrationPlotKind: 
  1484.                 WhatToPrint := PrintPlot;
  1485.             ResultsKind: 
  1486.                 if (CurrentTool = ruler) and (nLengths > 0) then
  1487.                     WhatToPrint := PrintLengths
  1488.                 else if (CurrentTool = PointingTool) and (nPoints > 0) then
  1489.                     WhatToPrint := PrintPoints
  1490.                 else if nAreas > 0 then
  1491.                     WhatToPrint := PrintAreas;
  1492.             otherwise
  1493.                 ;
  1494.         end;
  1495.         if (WhatToPrint = NothingToPRint) and (info <> NoInfo) then
  1496.             WhatToPrint := PrintImage;
  1497.     end;
  1498.  
  1499.  
  1500.     procedure UpdateFileMenu;
  1501.         var
  1502.             ShowItems, isSelection: boolean;
  1503.             i: integer;
  1504.             str, str2: str255;
  1505.             fwptr: WindowPtr;
  1506.             kind: integer;
  1507.     begin
  1508.         ShowItems := Info <> NoInfo;
  1509.         fwptr := FrontWindow;
  1510.         kind := WindowPeek(fwptr)^.WindowKind;
  1511.         SetMenuItem(FileMenuH, 4, ShowItems or (kind = ProfilePlotKind) or (kind = CalibrationPlotKind) or (kind = HistoKind));
  1512.         with info^ do
  1513.             isSelection := RoiShowing and (RoiType = RectRoi);
  1514.         if isSelection then begin
  1515.                 SetItem(FileMenuH, 7, 'Save Selection As TIFFâ•”');
  1516.                 SetItem(FileMenuH, 8, 'Save Selection As PICTâ•”');
  1517.             end
  1518.         else begin
  1519.                 SetItem(FileMenuH, 7, 'Save As TIFFâ•”');
  1520.                 SetItem(FileMenuH, 8, 'Save As PICTâ•”');
  1521.             end;
  1522.         for i := 6 to 8 do
  1523.             SetMenuItem(FileMenuH, i, ShowItems);
  1524.         if isSelection then
  1525.             str := 'Duplicate Selection'
  1526.         else
  1527.             str := 'Duplicate';
  1528.         SetItem(FileMenuH, 12, str);
  1529.         for i := 11 to 13 do
  1530.             SetMenuItem(FileMenuH, i, ShowItems);
  1531.         with info^ do
  1532.             if (PictureType <> pdp11) and (PictureType <> normal) and (PictureType <> PictFile) and (PictureType <> TiffFile) and (PictureType <> InvertedTIFF) then
  1533.                 SetMenuItem(FileMenuH, 11, false);
  1534.         FindWhatToPrint;
  1535.         case WhatToPrint of
  1536.             NothingToPrint: 
  1537.                 str := '';
  1538.             PrintImage: 
  1539.                 str := 'Image';
  1540.             PrintSelection: 
  1541.                 str := 'Selection';
  1542.             PrintPlot: 
  1543.                 str := 'Plot';
  1544.             PrintHistogram: 
  1545.                 str := 'Histogram';
  1546.             PrintAreas: 
  1547.                 str := 'Measurements';
  1548.             PrintLengths: 
  1549.                 str := 'Lengths';
  1550.             PrintPoints: 
  1551.                 str := 'Points';
  1552.         end;
  1553.         SetItem(FileMenuH, 17, concat('Print ', str, 'â•”'));
  1554.         SetMenuItem(FileMenuH, 17, WhatToPrint <> NothingToPrint);
  1555.         SetMenuItem(FileMenuH, 19, info^.RoiShowing);
  1556.     end;
  1557.  
  1558.  
  1559.     procedure UpdateMenus;
  1560.     begin
  1561.         UpdateFileMenu;
  1562.         UpdateEditMenu;
  1563.         UpdateOptionsMenu;
  1564.         UpdateFunctionsMenu;
  1565.         UpdateAnalysisMenu;
  1566.     end;
  1567.  
  1568.  
  1569.     procedure CloseAll;
  1570.     FORWARD;
  1571.  
  1572.  
  1573.     procedure DoMouseDown (event: EventRecord);
  1574.         var
  1575.             WhichWindow: WindowPtr;
  1576.             ThePart, ignore: integer;
  1577.     begin
  1578.         ThePart := FindWindow(event.where, WhichWindow);
  1579.         case ThePart of
  1580.             InDesk: 
  1581.                 ;
  1582.             InMenuBar: 
  1583.                 begin
  1584.                     UpdateMenus;
  1585.                     CheckWindowsMenuItem;
  1586.                     DoMenuEvent(MenuSelect(event.where));
  1587.                 end;
  1588.             InSysWindow: 
  1589.                 SystemClick(Event, WhichWindow);
  1590.             InContent: 
  1591.                 begin
  1592.                     if WhichWindow = ToolWindow then begin
  1593.                             DoMouseDownInTools(event.where);
  1594.                             exit(DoMouseDown);
  1595.                         end;
  1596.                     if WhichWindow = GrayMapWindow then begin
  1597.                             DoMouseDownInGrayMap;
  1598.                             exit(DoMouseDown)
  1599.                         end;
  1600.                     if WhichWindow = LUTWindow then begin
  1601.                             DoMouseDownInLUT(event);
  1602.                             exit(DoMouseDown)
  1603.                         end;
  1604.                     if WhichWindow = PasteControl then begin
  1605.                             DoMouseDownInPasteControl(event.where);
  1606.                             exit(DoMouseDown)
  1607.                         end;
  1608.                     if WhichWindow <> FrontWindow then
  1609.                         SelectWindow(WhichWindow)
  1610.                     else
  1611.                         DoMouseDownInWindow(Event, WhichWindow);
  1612.                 end;
  1613.             InDrag: 
  1614.                 DoDrag(WhichWindow, event.where);
  1615.             InGrow: 
  1616.                 DoGrow(WhichWindow, event);
  1617.             InGoAway: 
  1618.                 if TrackGoAway(WhichWindow, event.where) then
  1619.                     if OptionKeyDown then
  1620.                         CloseAll
  1621.                     else begin
  1622.                             StopDigitizing;
  1623.                             ignore := CloseAWindow(WhichWindow);
  1624.                         end;
  1625.             InZoomIn, InZoomOut: 
  1626.                 begin
  1627.                     ScaleToFit;
  1628.                     if info^.ScaleToFitWindow then
  1629.                         DoZoomIn;
  1630.                 end;
  1631.         end;
  1632.     end;
  1633.  
  1634.  
  1635.     procedure NudgeRoi (key: integer);
  1636.         var
  1637.             dh, dv: integer;
  1638.     begin
  1639.         with info^ do begin
  1640.                 if not RoiShowing then
  1641.                     exit(NudgeRoi);
  1642.                 case key of
  1643.                     LeftArrow: 
  1644.                         begin
  1645.                             dh := -1;
  1646.                             dv := 0
  1647.                         end;
  1648.                     RightArrow: 
  1649.                         begin
  1650.                             dh := 1;
  1651.                             dv := 0
  1652.                         end;
  1653.                     UpArrow: 
  1654.                         begin
  1655.                             dh := 0;
  1656.                             dv := -1
  1657.                         end;
  1658.                     DownArrow: 
  1659.                         begin
  1660.                             dh := 0;
  1661.                             dv := 1
  1662.                         end;
  1663.                 end;
  1664.                 OffsetRgn(osroiRgn, dh, dv);
  1665.                 osroiRect := osroiRgn^^.rgnBBox;
  1666.                 roiRect := osroiRect;
  1667.                 OffscreenToScreenRect(roiRect);
  1668.                 RoiNudged := true;
  1669.             end;
  1670.     end;
  1671.  
  1672.  
  1673.     procedure DoKeyDown (event: EventRecord);
  1674.         var
  1675.             Ch: char;
  1676.             ich: integer;
  1677.     begin
  1678.         Ch := chr(BitAnd(Event.message, 255));
  1679.         ich := ord(ch);
  1680.         if BitAnd(Event.modifiers, CmdKey) = CmdKey then begin
  1681.                 UpdateMenus;
  1682.                 CheckWindowsMenuItem;
  1683.                 DoMenuEvent(MenuKey(Ch));
  1684.                 exit(DoKeyDown)
  1685.             end;
  1686.         if CurrentTool = TextTool then
  1687.             DrawCharacter(ch)
  1688.         else if ch = BackSpace then begin
  1689.                 if OpPending and (CurrentOp = PasteOp) then begin
  1690.                         OpPending := false;
  1691.                         KillRoi;
  1692.                     end
  1693.                 else
  1694.                     DoClear
  1695.             end
  1696.         else if (ich >= LeftArrow) and (ich <= DownArrow) then
  1697.             NudgeRoi(ich);
  1698.     end;
  1699.  
  1700.  
  1701.     procedure ActivateWindow;
  1702.     begin
  1703.         with info^ do begin
  1704.                 SetPort(info^.wptr);
  1705.                 IsInsertionPoint := false;
  1706.                 WhatToUndo := NothingToUndo;
  1707.                 DrawLabels;
  1708.                 MouseState := NotInRoi;
  1709.             end;
  1710.     end;
  1711.  
  1712.  
  1713.     procedure DoActivate (event: EventRecord);
  1714.         var
  1715.             WhichWindow: WindowPtr;
  1716.             Activating, SwitchingWindows, isOK: boolean;
  1717.             I, kind: integer;
  1718.             NewInfo: InfoPtr;
  1719.     begin
  1720.         WhichWindow := WindowPtr(event.message);
  1721.         kind := WindowPeek(WhichWindow)^.WindowKind;
  1722.         Activating := odd(event.modifiers);
  1723.         if kind = PicKind then begin
  1724.                 if Activating then begin
  1725.                         NewInfo := pointer(WindowPeek(WhichWindow)^.RefCon);
  1726.                         SwitchingWindows := NewInfo <> Info;
  1727.                         if SwitchingWindows then begin
  1728.                                 StopDigitizing;
  1729.                                 SaveRoi;
  1730.                                 StopThresholding;
  1731.                             end;
  1732.                         Info := NewInfo;
  1733.                         if SwitchingWindows then
  1734.                             ActivateWindow
  1735.                         else
  1736.                             SetPort(info^.wptr);
  1737.                         with info^ do begin
  1738.                                 if (LutMode = GrayScale) or (LutMode = CustomGrayscale) then
  1739.                                     DrawGrayMap;
  1740.                                 if not UndoFromClip then
  1741.                                     ShowRoi;
  1742.                                 LoadLUT(cTable);
  1743.                             end;
  1744.                         GenerateValues;
  1745.                     end
  1746.                 else
  1747.                     KillOperation; {Deactivate}
  1748.             end;
  1749.         if not activating then begin
  1750.                 WhichWindow := FrontWindow;
  1751.                 kind := WindowPeek(WhichWindow)^.WindowKind;
  1752.                 if kind < 0 then
  1753.                     ConvertClipboard; {DA has become active}
  1754.             end;
  1755.     end;
  1756.  
  1757.  
  1758.     procedure DoUpdate (event: EventRecord);
  1759.         var
  1760.             WhichWindow: WindowPtr;
  1761.             SaveInfo: InfoPtr;
  1762.             kind: integer;
  1763.     begin
  1764.         WhichWindow := WindowPtr(event.message);
  1765.         kind := WindowPeek(WhichWindow)^.WindowKind;
  1766.         BeginUpdate(WhichWindow);
  1767.         case kind of
  1768.             Pickind: 
  1769.                 begin
  1770.                     SaveInfo := info;
  1771.                     Info := pointer(WindowPeek(WhichWindow)^.RefCon);
  1772.                     if info <> NoInfo then begin
  1773.                             UpdatePicWindow;
  1774.                             DrawMyGrowIcon(info^.wptr);
  1775.                         end
  1776.                     else
  1777.                         beep;
  1778.                     info := SaveInfo;
  1779.                 end;
  1780.             ToolKind: 
  1781.                 DrawTools;
  1782.             GrayMapKind: 
  1783.                 DrawGrayMap;
  1784.             LUTKind: 
  1785.                 DrawLUT;
  1786.             ResultsKind: 
  1787.                 begin
  1788.                     DrawLabels;
  1789.                     if GetResultsType <> NoResults then
  1790.                         ShowResults;
  1791.                 end;
  1792.             HistoKind: 
  1793.                 DrawHistogram;
  1794.             ProfilePlotKind, CalibrationPlotKind: 
  1795.                 DrawPlot;
  1796.             PasteControlKind: 
  1797.                 DrawPasteControl;
  1798.         end;
  1799.         EndUpdate(WhichWindow);
  1800.     end;
  1801.  
  1802.  
  1803.     procedure DoDiskInsert (event: EventRecord);
  1804. { Process disk insertion event, check for damaged or uninitialized disks. }
  1805.         var
  1806.             p: point;
  1807.             intjunk: integer;
  1808.     begin
  1809.         if (HiWord(event.message) <> NoErr) then begin
  1810.                 DiLoad;
  1811.                 SetPt(p, 100, 80);
  1812.                 intjunk := DiBadMount(p, event.message);
  1813.                 DiUnload;
  1814.             end;
  1815.     end;
  1816.  
  1817.  
  1818.     function HandleEvents: boolean;
  1819.         var
  1820.             Event: EventRecord;
  1821.             result: boolean;
  1822.             theDialog: DialogPtr;
  1823.             ItemHit: integer;
  1824.     begin
  1825.         if GetNextEvent(EveryEvent, Event) then begin
  1826.                 case Event.what of
  1827.                     KeyDown, AutoKey: 
  1828.                         DoKeyDown(Event);
  1829.                     MouseDown: 
  1830.                         DoMouseDown(Event);
  1831.                     ActivateEvt: 
  1832.                         DoActivate(Event);
  1833.                     DiskEvt: 
  1834.                         DoDiskInsert(Event);
  1835.                     UpdateEvt: 
  1836.                         DoUpdate(Event);
  1837.                     otherwise {Do nothing}
  1838.                 end;
  1839.                 HandleEvents := true
  1840.             end
  1841.         else
  1842.             HandleEvents := false;
  1843.     end;
  1844.  
  1845.  
  1846.     procedure ShowInsertionPoint;
  1847.         var
  1848.             tRect: rect;
  1849.             Loc: point;
  1850.             height, imag: integer;
  1851.     begin
  1852.         if not isInsertionPoint then
  1853.             exit(ShowInsertionPoint);
  1854.         if (TickCount mod (BlinkTime * 2)) < BlinkTime then
  1855.             exit(ShowInsertionPoint);
  1856.         if info = NoInfo then
  1857.             exit(ShowInsertionPoint);
  1858.         Loc := InsertionPoint;
  1859.         OffscreenToScreen(loc);
  1860.         with info^, tRect do begin
  1861.                 imag := trunc(magnification + 0.5);
  1862.                 height := CurrentSize * imag;
  1863.                 height := height - height div 4;
  1864.                 left := loc.h;
  1865.                 bottom := loc.v - imag + 1;
  1866.                 top := bottom - height;
  1867.                 right := left + 1;
  1868.                 PenNormal;
  1869.                 PenSize(imag, imag);
  1870.                 PenMode(PatXor);
  1871.                 FrameRect(tRect);
  1872.                 ticks := TickCount + 3;
  1873.                 repeat
  1874.                 until TickCount > ticks;
  1875.                 FrameRect(tRect);
  1876.             end;
  1877.     end;
  1878.  
  1879.  
  1880.     procedure DrawROI;
  1881.         var
  1882.             tPort: GrafPtr;
  1883.             tRect: rect;
  1884.             SaveUndoFromClip: boolean;
  1885.             RoiStretchHandle: rect;
  1886.     begin
  1887.         with Info^ do
  1888.             if RoiShowing then begin
  1889.                     if OpPending then
  1890.                         DoOperation(CurrentOp);
  1891.                     GetPort(tPort);
  1892.                     SetPort(GrafPtr(Info^.osPort));
  1893.                     PenNormal;
  1894.                     if not ((MouseState = DownInRoi) and OpPending) then
  1895.                         if PicSize <= UndoBufSize then begin
  1896.                                 with info^.osPort^ do begin
  1897.                                         fgColor := BlackC;
  1898.                                         bkColor := WhiteC;
  1899.                                     end;
  1900.                                 if RoiType = RectRoi then begin
  1901.                                         with osroiRect do begin
  1902.                                                 SetRect(RoiStretchHandle, right - RoiHandleSize, bottom - RoiHandleSize, right, bottom);
  1903.                                                 if ((right - left) > RoiHandleSize) and ((bottom - top) > RoiHandleSize) then
  1904.                                                     PaintRect(RoiStretchHandle);
  1905.                                             end;
  1906.                                     end;
  1907.                                 PatIndex := (PatIndex + 1) mod 8;
  1908.                                 PenPat(pat[PatIndex]);
  1909.                                 FrameRgn(osroiRgn);
  1910.                                 with info^.osPort^ do begin
  1911.                                         fgColor := ForegroundColor;
  1912.                                         bkColor := BackgroundColor;
  1913.                                     end;
  1914.                             end;
  1915.                     if PicSize > UndoBufSize then begin
  1916.                             if magnification < 1.0 then
  1917.                                 PenSize(2, 2);
  1918.                             PatIndex := (PatIndex + 1) mod 8;
  1919.                             PenPat(pat[PatIndex]);
  1920.                             PenMode(PatXor);
  1921.                             FrameRgn(osroiRgn);
  1922.                             if MouseState = DownInRoi then begin
  1923.                                     UnionRect(RoiRect, OldRoiRect, tRect);
  1924.                                     UpdateScreen(tRect);
  1925.                                 end
  1926.                             else
  1927.                                 UpdateScreen(RoiRect);
  1928.                             FrameRgn(osroiRgn);
  1929.                         end
  1930.                     else begin
  1931.                             tRect := RoiRect;
  1932.                             if MouseState = DownInRoi then
  1933.                                 UnionRect(RoiRect, OldRoiRect, tRect)
  1934.                             else if RoiNudged then begin
  1935.                                     tRect := osroiRect;
  1936.                                     InsetRect(tRect, -2, -2);
  1937.                                     OffscreenToScreenRect(tRect);
  1938.                                     RoiNudged := false;
  1939.                                 end;
  1940.                             UpdateScreen(tRect);
  1941.                             SaveUndoFromClip := UndoFromClip;
  1942.                             UndoFromClip := false;
  1943.                             Undo;
  1944.                             UndoFromClip := SaveUndoFromClip;
  1945.                         end;
  1946.                     SetPort(tPort);
  1947.                 end; {if roi showing}
  1948.     end;
  1949.  
  1950.  
  1951.     procedure MoveRoi (loc, osloc: point);
  1952.         var
  1953.             osdh, osdv: integer;
  1954.     begin
  1955.         with info^ do begin
  1956.                 osdh := osloc.h - osMouseDownLoc.h;
  1957.                 osdv := osloc.v - osMouseDownLoc.v;
  1958.                 if RoiMovementState = Constrained then begin
  1959.                         if osdv <> 0 then
  1960.                             RoiMovementState := ConstrainedV
  1961.                         else if osdh <> 0 then
  1962.                             RoiMovementState := ConstrainedH
  1963.                     end;
  1964.                 if RoiMovementState = ConstrainedH then
  1965.                     osdv := 0
  1966.                 else if RoiMovementState = ConstrainedV then
  1967.                     osdh := 0;
  1968.                 if not OpPending then
  1969.                     with osroiRect do begin
  1970.                             if (left + osdh < 0) and not StretchMode then
  1971.                                 osdh := -left;
  1972.                             if (top + osdv < 0) and not StretchMode then
  1973.                                 osdv := -top;
  1974.                             if right + osdh > PicRect.right then
  1975.                                 osdh := PicRect.right - right;
  1976.                             if bottom + osdv > PicRect.bottom then
  1977.                                 osdv := PicRect.bottom - bottom;
  1978.                         end;
  1979.                 OldRoiRect := RoiRect;
  1980.                 if StretchMode then begin
  1981.                         measuring := false;
  1982.                         if ValuesMode <> WidthValues then begin
  1983.                                 ValuesMode := WidthValues;
  1984.                                 DrawLabels;
  1985.                             end;
  1986.                         with osroiRect do begin
  1987.                                 right := right + osdh;
  1988.                                 if right < left + 2 then
  1989.                                     right := left + 2;
  1990.                                 bottom := bottom + osdv;
  1991.                                 if bottom < top + 2 then
  1992.                                     bottom := top + 2;
  1993.                                 Show2Values(right - left, bottom - top);
  1994.                                 MakeRegion;
  1995.                             end
  1996.                     end
  1997.                 else begin
  1998.                         if ValuesMode <> PixelValues then begin
  1999.                                 ValuesMode := PixelValues;
  2000.                                 DrawLabels;
  2001.                             end;
  2002.                         OffsetRgn(osroiRgn, osdh, osdv);
  2003.                         with osroiRect do
  2004.                             Show3Values(left, top, 0);
  2005.                     end;
  2006.                 osroiRect := osroiRgn^^.rgnBBox;
  2007.                 roiRect := osroiRect;
  2008.                 OffscreenToScreenRect(roiRect);
  2009.                 MouseDownLoc := loc;
  2010.                 osMouseDownLoc := osloc;
  2011.             end;
  2012.     end;
  2013.  
  2014.  
  2015.     procedure SelectCursor;
  2016.         var
  2017.             loc, osloc, gloc: point;
  2018.             where, kind, i, color, x, y, margin: integer;
  2019.             WhichWindow: WindowPtr;
  2020.             MouseInRoi: boolean;
  2021.             tPort: GrafPtr;
  2022.             fwptr: WindowPtr;
  2023.             cvalue, xscale: extended;
  2024.             RoiStretchHandle: rect;
  2025.             MovingRoi: boolean;
  2026.             xvalue: integer;
  2027.     begin
  2028.         if PasteControl <> nil then begin
  2029.                 fwptr := FrontWindow;
  2030.                 if WindowPeek(fwptr)^.WindowKind <> PasteControlKind then
  2031.                     BringToFront(PasteControl);
  2032.             end;
  2033.         GetPort(tPort);
  2034.         SetPort(ScreenPort);
  2035.         GetMouse(gloc);
  2036.         loc := gloc;
  2037.         where := FindWindow(gloc, WhichWindow);
  2038.         kind := WindowPeek(WhichWindow)^.WindowKind;
  2039.         if kind < 0 then begin
  2040.                 SetPort(tPort);
  2041.                 exit(SelectCursor)
  2042.             end; {System Window}
  2043.         if where <> InContent then begin
  2044.                 InitCursor;
  2045.                 SetPort(tPort);
  2046.                 exit(SelectCursor)
  2047.             end;
  2048.         case kind of
  2049.             PicKind: 
  2050.                 begin
  2051.                     if Info = NoInfo then begin
  2052.                             SetPort(tPort);
  2053.                             exit(SelectCursor)
  2054.                         end;
  2055.                     SetPort(info^.wptr);
  2056.                     GlobalToLocal(loc);
  2057.                     osloc := loc;
  2058.                     ScreenToOffscreen(osloc);
  2059.                     MovingRoi := false;
  2060.                     with info^ do begin
  2061.                             SelectionMode := NewSelection;
  2062.                             if RoiShowing and isSelectionTool then begin
  2063.                                     if OptionKeyDown then
  2064.                                         SelectionMode := SubSelection
  2065.                                     else if ControlKeyDown then
  2066.                                         SelectionMode := AddSelection;
  2067.                                 end;
  2068.                             if RoiShowing and (SelectionMode = NewSelection) then
  2069.                                 MouseInRoi := PtInRgn(osloc, osroiRgn)
  2070.                             else
  2071.                                 MouseInRoi := false
  2072.                         end; {with}
  2073.                     if MouseInRoi or (MouseState = DownInRoi) then begin
  2074.                             if MouseState = NotInRoi then
  2075.                                 MouseState := InRoi;
  2076.                             InitCursor;
  2077.                             if button then begin
  2078.                                     if MouseState = InRoi then begin
  2079.                                             if OpPending and (CurrentOp <> PasteOp) then
  2080.                                                 SetupUndo;
  2081.                                             MouseState := DownInRoi;
  2082.                                             MouseDownLoc := loc;
  2083.                                             osMouseDownLoc := osloc;
  2084.                                             with info^ do
  2085.                                                 if RoiType = RectRoi then begin
  2086.                                                         if magnification > 1.0 then
  2087.                                                             margin := 0
  2088.                                                         else
  2089.                                                             margin := 2;
  2090.                                                         with osroiRect do
  2091.                                                             SetRect(RoiStretchHandle, right - RoiHandleSize - margin, bottom - RoiHandleSize - margin, right, bottom);
  2092.                                                         StretchMode := PtInRect(osloc, RoiStretchHandle);
  2093.                                                     end;
  2094.                                             if ShiftKeyDown then
  2095.                                                 RoiMovementState := Constrained
  2096.                                             else
  2097.                                                 RoiMovementState := Unconstrained;
  2098.                                         end;
  2099.                                     MoveRoi(loc, osloc);
  2100.                                     MovingRoi := true;
  2101.                                 end
  2102.                             else
  2103.                                 MouseState := InRoi
  2104.                         end
  2105.                     else begin
  2106.                             MouseState := NotInRoi;
  2107.                             if SpaceBarDown and (CurrentTool <> TextTool) then
  2108.                                 SetCursor(ToolCursor[Grabber])
  2109.                             else if SelectionMode = AddSelection then
  2110.                                 SetCursor(CrossPlusCursor)
  2111.                             else if SelectionMode = SubSelection then
  2112.                                 SetCursor(CrossMinusCursor)
  2113.                             else if (CurrentTool = MagnifyingGlass) and OptionKeyDown then
  2114.                                 SetCursor(GlassMinusCursor)
  2115.                             else
  2116.                                 SetCursor(ToolCursor[CurrentTool]);
  2117.                         end;
  2118.                     if not MovingRoi then begin
  2119.                             if ValuesMode <> PixelValues then begin
  2120.                                     ValuesMode := PixelValues;
  2121.                                     DrawLabels;
  2122.                                 end;
  2123.                             with osloc do
  2124.                                 Show3Values(h, v, MyGetPixel(h, v));
  2125.                         end;
  2126.                 end;
  2127.             HistoKind: 
  2128.                 begin
  2129.                     if ValuesMode <> xyValues then begin
  2130.                             ValuesMode := xyValues;
  2131.                             DrawLabels;
  2132.                         end;
  2133.                     SetCursor(ToolCursor[SelectionTool]);
  2134.                     SetPort(HistoWindow);
  2135.                     GlobalToLocal(loc);
  2136.                     Show2Values(loc.h, histogram[loc.h]);
  2137.                 end;
  2138.             ProfilePlotKind, CalibrationPlotKind: 
  2139.                 begin
  2140.                     if ValuesMode <> xyValues then begin
  2141.                             ValuesMode := xyValues;
  2142.                             DrawLabels;
  2143.                         end;
  2144.                     SetCursor(ToolCursor[SelectionTool]);
  2145.                     SetPort(PlotWindow);
  2146.                     GlobalToLocal(loc);
  2147.                     xscale := PlotCount / (PlotWidth - PlotRightMargin - PlotLeftMargin);
  2148.                     xvalue := trunc((loc.h - PlotLeftMargin) * xscale);
  2149.                     if (xvalue >= 0) and (xvalue < PlotWidth) then
  2150.                         if kind = CalibrationPlotKind then
  2151.                             Show2CalibratedValues(xvalue, xvalue, false)
  2152.                         else
  2153.                             Show2CalibratedValues(xvalue, PlotData[xvalue], true);
  2154.                 end;
  2155.             LUTKind: 
  2156.                 begin
  2157.                     if ValuesMode <> IndexValue then begin
  2158.                             ValuesMode := IndexValue;
  2159.                             DrawLabels
  2160.                         end;
  2161.                     SetPort(LUTWindow);
  2162.                     GlobalToLocal(loc);
  2163.                     if (CurrentTool = LutTool) or (CurrentTool = Wand) then begin
  2164.                             if loc.v < 256 then
  2165.                                 SetCursor(LUTCursor)
  2166.                             else
  2167.                                 InitCursor
  2168.                         end
  2169.                     else
  2170.                         SetCursor(PickerCursor);
  2171.                     if loc.v < 256 then begin
  2172.                             if info^.calibrated then
  2173.                                 cvalue := value[loc.v]
  2174.                             else
  2175.                                 cvalue := noValue;
  2176.                             Show1Value(loc.v, cvalue);
  2177.                         end
  2178.                     else begin
  2179.                             color := 0;
  2180.                             for i := 1 to nExtraColors + 2 do
  2181.                                 if PtInRect(loc, ExtraColorsRect[i]) then
  2182.                                     Color := ExtraColorsEntry[i];
  2183.                             if info^.calibrated then
  2184.                                 cvalue := value[color]
  2185.                             else
  2186.                                 cvalue := noValue;
  2187.                             Show1Value(color, cvalue);
  2188.                         end;
  2189.                 end;
  2190.             GrayMapKind: 
  2191.                 SetCursor(gmCursor);
  2192.             otherwise
  2193.                 InitCursor;
  2194.         end; {case}
  2195.         SetPort(tPort);
  2196.     end;
  2197.  
  2198.  
  2199.     procedure CloseAll;
  2200.         var
  2201.             i, j, result: integer;
  2202.             WPeek, NextWPeek: WindowPeek;
  2203.             ignore: boolean;
  2204.     begin
  2205.         InitCursor;
  2206.         WPeek := WindowPeek(FrontWindow);
  2207.         StopDigitizing;
  2208.         while wpeek <> nil do begin
  2209.                 NextWPeek := WPeek^.NextWindow;
  2210.                 if WPeek^.WindowKind = PicKind then begin
  2211.                         Info := pointer(WPeek^.RefCon);
  2212.                         result := CloseAWindow(info^.wptr);
  2213.                         for j := 1 to 2 do
  2214.                             ignore := HandleEvents;
  2215.                         if result = cancel then begin
  2216.                                 ActivateWindow;
  2217.                                 finished := false;
  2218.                                 exit(CloseAll)
  2219.                             end;
  2220.                     end;
  2221.                 wpeek := NextWPeek;
  2222.             end;
  2223.     end;
  2224.  
  2225.  
  2226.     procedure DoStartup;
  2227.   {Process Finder startup information}
  2228.         var
  2229.             message, ndocs, err, i, j: integer;
  2230.             DocInfo: AppFile;
  2231.             DefaultPalette, OpenedOK: boolean;
  2232.             palettename: str255;
  2233.             PaletteFile: boolean;
  2234.             ignore, PrintDocs: boolean;
  2235.  
  2236.         procedure PrintDocument;
  2237.             var
  2238.                 i: integer;
  2239.         begin
  2240.             WhatToPrint := PrintImage;
  2241.             Print(false);
  2242.             DoClose;
  2243.             for i := 1 to 10 do
  2244.                 ignore := HandleEvents;
  2245.         end;
  2246.  
  2247.     begin
  2248.         for j := 1 to 10 do
  2249.             ignore := HandleEvents;
  2250.         PaletteFile := false;
  2251.         CountAppFiles(message, ndocs);
  2252.         PrintDocs := message = appPrint;
  2253.         if ndocs >= 1 then
  2254.             for i := 1 to ndocs do begin
  2255.                     GetAppFiles(i, DocInfo);
  2256.                     with DocInfo do begin
  2257.                             if ftype = 'ICOL' then begin
  2258.                                     PaletteFile := true;
  2259.                                     palettename := docinfo.fname;
  2260.                                     ClrAppFiles(i)
  2261.                                 end;
  2262.                             if fType = 'IPIC' then begin
  2263.                                     WhatToOpen := OpenImage;
  2264.                                     OpenFile(fName, vRefNum);
  2265.                                     for j := 1 to 10 do
  2266.                                         ignore := HandleEvents;
  2267.                                     ClrAppFiles(i);
  2268.                                     if PrintDocs then
  2269.                                         PrintDocument;
  2270.                                 end;
  2271.                             if fType = 'TIFF' then begin
  2272.                                     WhatToOpen := OpenTIFF;
  2273.                                     OpenFile(fName, vRefNum);
  2274.                                     for j := 1 to 10 do
  2275.                                         ignore := HandleEvents;
  2276.                                     ClrAppFiles(i);
  2277.                                     if PrintDocs then
  2278.                                         PrintDocument;
  2279.                                 end;
  2280.                             if fType = 'PICT' then begin
  2281.                                     OpenedOK := OpenPICT(fName, vRefNum, false);
  2282.                                     for j := 1 to 10 do
  2283.                                         ignore := HandleEvents;
  2284.                                     ClrAppFiles(i);
  2285.                                     if not OpenedOK then
  2286.                                         exit(DoStartup);
  2287.                                     if PrintDocs then
  2288.                                         PrintDocument;
  2289.                                 end;
  2290.                         end; {with}
  2291.                 end;
  2292.         if PaletteFile then
  2293.             InitColor(PaletteName, DocInfo.vRefNum);
  2294.     end;
  2295.  
  2296.  
  2297.     procedure Shutdown;
  2298.         var
  2299.             AlertID: integer;
  2300.     begin
  2301.         if (UnsavedAreas > 0) or (UnsavedLengths > 0) or (UnsavedPoints > 0) then begin
  2302.                 InitCursor;
  2303.                 AlertID := alert(500, nil);
  2304.                 if AlertID = CancelResetID then begin
  2305.                         finished := false;
  2306.                         exit(Shutdown)
  2307.                     end;
  2308.             end;
  2309.         CloseAll;
  2310.         ConvertClipboard;
  2311.     end;
  2312.  
  2313.  
  2314. begin
  2315.     Init;
  2316.     SetupMenus;
  2317.     GetSettings;
  2318.     AllocateBuffers;
  2319.     GetPictFromScrap;
  2320.     DoStartup;
  2321.     UnloadSeg(@Init);
  2322. {InitUser;}
  2323.     repeat
  2324.         SystemTask;
  2325.         if not HandleEvents then
  2326.             if info^.RoiShowing then
  2327.                 DrawRoi;
  2328.         ShowInsertionPoint;
  2329.         SelectCursor;
  2330.         if Digitizing then begin
  2331.                 GetFrame;
  2332.                 if ContinuousHistogram then
  2333.                     ShowContinuousHistogram;
  2334.             end;
  2335.         if Finished then
  2336.             Shutdown;
  2337.     until finished;
  2338.     isOK := LoadCLUTResource(AppleDefaultCLUT);
  2339.     RestoreScreen; {Force Finder to redraw color icons}
  2340. end.